package com.example.alltestapplication

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.media.AudioAttributes
import android.media.AudioFormat
import android.media.AudioManager
import android.media.AudioTrack
import android.media.MediaCodec
import android.media.MediaExtractor
import android.media.MediaFormat
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.provider.Settings
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Button
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat
import com.example.alltestapplication.ui.theme.AllTestApplicationTheme
import java.io.File
import java.nio.ByteBuffer
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.coroutines.yield

class AudioTrackTestActivity : ComponentActivity() {
    
    // 使用SupervisorJob确保一个子协程失败不会影响全局
    private val coroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
    private val hasPermission = mutableStateOf(false)
    private var playJob: Job? = null
    private var isPlaying = mutableStateOf(false)
    
    private val requestPermissionLauncher = registerForActivityResult(
        ActivityResultContracts.RequestMultiplePermissions()
    ) { permissions ->
        if (permissions.entries.all { it.value }) {
            hasPermission.value = true
            Toast.makeText(this, "权限已授予，可以播放音频", Toast.LENGTH_SHORT).show()
        } else {
            hasPermission.value = false
            Toast.makeText(this, "需要存储权限才能访问音频文件", Toast.LENGTH_LONG).show()
        }
    }
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        
        checkPermissionStatus()
        
        setContent {
            AllTestApplicationTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    AudioTestScreen(
                        modifier = Modifier.padding(innerPadding),
                        hasPermission = hasPermission.value,
                        isPlaying = isPlaying.value,
                        onRequestPermission = { requestPermissions() },
                        onPlayMusic = { streamType -> playAudio(streamType) },
                        onPlayVoiceCall = { streamType -> playAudio(streamType) },
                        onPlaySystem = { streamType -> playAudio(streamType) },
                        onPlayRing = { streamType -> playAudio(streamType) }
                    )
                }
            }
        }
    }
    
    private fun checkPermissionStatus() {
        val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            arrayOf(Manifest.permission.READ_MEDIA_AUDIO)
        } else {
            arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE)
        }
        
        hasPermission.value = permissions.all { permission ->
            ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED
        }
    }
    
    private fun requestPermissions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !Environment.isExternalStorageManager()) {
            try {
                val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
                val uri = Uri.fromParts("package", packageName, null)
                intent.data = uri
                startActivity(intent)
                Toast.makeText(this, "请授予所有文件访问权限", Toast.LENGTH_LONG).show()
            } catch (e: Exception) {
                val intent = Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION)
                startActivity(intent)
            }
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            requestPermissionLauncher.launch(arrayOf(Manifest.permission.READ_MEDIA_AUDIO))
        } else {
            requestPermissionLauncher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE))
        }
    }
    
    private fun playAudio(streamType: Int) {
        if (!hasPermission.value) {
            Toast.makeText(this, "请先授予存储权限", Toast.LENGTH_LONG).show()
            return
        }
        
        // 取消当前播放并启动新播放
        coroutineScope.launch {
            try {
                // 先取消当前播放
                stopAudioImmediately()
                // 确保UI状态更新
                isPlaying.value = true
                // 启动新播放任务
                playJob = launchPlayJob(streamType)
            } catch (e: Exception) {
                isPlaying.value = false
                Toast.makeText(this@AudioTrackTestActivity, "播放切换出错: ${e.message}", Toast.LENGTH_SHORT).show()
            }
        }
    }
    
    private suspend fun stopAudioImmediately() {
        try {
            playJob?.cancelAndJoin()
            playJob = null
            // 确保有时间完全释放资源
            delay(100)
            yield()
        } catch (e: Exception) {
            // 忽略取消错误
        }
    }
    
    private fun launchPlayJob(streamType: Int) = coroutineScope.launch {
        var localAudioTrack: AudioTrack? = null
        var codec: MediaCodec? = null
        var extractor: MediaExtractor? = null
        
        try {
            val filePath = "${Environment.getExternalStorageDirectory().path}/recording8557627186354108417.3gpp"
            val audioFile = File(filePath)
            
            if (!audioFile.exists()) {
                withContext(Dispatchers.Main) {
                    Toast.makeText(
                        this@AudioTrackTestActivity,
                        "音频文件不存在: $filePath",
                        Toast.LENGTH_LONG
                    ).show()
                    isPlaying.value = false
                }
                return@launch
            }
            
            // 创建MediaExtractor
            extractor = MediaExtractor().apply {
                withContext(Dispatchers.IO) {
                    setDataSource(filePath)
                }
            }
            
            // 查找音频轨道
            var audioTrackIndex = -1
            var format: MediaFormat? = null
            
            for (i in 0 until extractor.trackCount) {
                val f = extractor.getTrackFormat(i)
                val mime = f.getString(MediaFormat.KEY_MIME)
                if (mime?.startsWith("audio/") == true) {
                    audioTrackIndex = i
                    format = f
                    break
                }
            }
            
            if (audioTrackIndex < 0 || format == null) {
                withContext(Dispatchers.Main) {
                    Toast.makeText(
                        this@AudioTrackTestActivity,
                        "找不到音频轨道",
                        Toast.LENGTH_LONG
                    ).show()
                    isPlaying.value = false
                }
                return@launch
            }
            
            extractor.selectTrack(audioTrackIndex)
            
            // 获取MIME类型并创建解码器
            val mime = format.getString(MediaFormat.KEY_MIME) ?: "audio/3gpp"
            codec = MediaCodec.createDecoderByType(mime)
            codec.configure(format, null, null, 0)
            codec.start()
            
            // 创建AudioTrack
            val sampleRate = 8000 // AMR-NB固定为8000Hz
            val channelConfig = AudioFormat.CHANNEL_OUT_MONO // 单声道
            val audioFormat = AudioFormat.ENCODING_PCM_16BIT // 16位PCM
            val minBufferSize = AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat)
            
            localAudioTrack = AudioTrack.Builder()
                .setAudioAttributes(
                    AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                        .setLegacyStreamType(streamType)
                        .build()
                )
                .setAudioFormat(
                    AudioFormat.Builder()
                        .setSampleRate(sampleRate)
                        .setEncoding(audioFormat)
                        .setChannelMask(channelConfig)
                        .build()
                )
                .setBufferSizeInBytes(minBufferSize)
                .setTransferMode(AudioTrack.MODE_STREAM)
                .build()
            
            localAudioTrack.play()
            
            // 解码循环
            val inputBuffers = codec.inputBuffers
            val outputBuffers = codec.outputBuffers
            val bufferInfo = MediaCodec.BufferInfo()
            var sawInputEOS = false
            var sawOutputEOS = false
            
            while (!sawOutputEOS) {
                // 检查协程是否已取消
                if (!isActive) {
                    break
                }
                
                // 输入AMR数据到解码器
                if (!sawInputEOS) {
                    val inputBufferIndex = codec.dequeueInputBuffer(10)
                    if (inputBufferIndex >= 0) {
                        val inputBuffer = inputBuffers[inputBufferIndex]
                        val sampleSize = extractor.readSampleData(inputBuffer, 0)
                        
                        if (sampleSize < 0) {
                            codec.queueInputBuffer(
                                inputBufferIndex,
                                0,
                                0,
                                0L,
                                MediaCodec.BUFFER_FLAG_END_OF_STREAM
                            )
                            sawInputEOS = true
                        } else {
                            val presentationTimeUs = extractor.sampleTime
                            codec.queueInputBuffer(
                                inputBufferIndex,
                                0,
                                sampleSize,
                                presentationTimeUs,
                                0
                            )
                            extractor.advance()
                        }
                    }
                }
                
                // 输出PCM数据到AudioTrack
                val outputBufferIndex = codec.dequeueOutputBuffer(bufferInfo, 10)
                if (outputBufferIndex >= 0) {
                    val outputBuffer = outputBuffers[outputBufferIndex]
                    
                    if (bufferInfo.size > 0) {
                        val chunk = ByteArray(bufferInfo.size)
                        outputBuffer.get(chunk)
                        outputBuffer.clear()
                        
                        // 检查再次协程是否已取消
                        if (!isActive) {
                            break
                        }
                        
                        // 写入AudioTrack
                        localAudioTrack.write(chunk, 0, chunk.size)
                    }
                    
                    codec.releaseOutputBuffer(outputBufferIndex, false)
                    
                    if ((bufferInfo.flags and MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                        sawOutputEOS = true
                    }
                }
                
                // 让出执行权，给其他协程处理取消的机会
                yield()
            }
            
            // 播放完成提示
            if (isActive) {
                withContext(Dispatchers.Main) {
                    Toast.makeText(
                        this@AudioTrackTestActivity,
                        "播放完成",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }
            
        } catch (e: CancellationException) {
            // 协程被取消，不显示错误
        } catch (e: Exception) {
            withContext(Dispatchers.Main) {
                Toast.makeText(
                    this@AudioTrackTestActivity,
                    "播放出错: ${e.message}",
                    Toast.LENGTH_LONG
                ).show()
            }
            e.printStackTrace()
        } finally {
            // 释放所有资源
            try {
                codec?.stop()
                codec?.release()
            } catch (e: Exception) {
                // 忽略释放异常
            }
            
            try {
                extractor?.release()
            } catch (e: Exception) {
                // 忽略释放异常
            }
            
            try {
                if (localAudioTrack?.state == AudioTrack.STATE_INITIALIZED) {
                    localAudioTrack.stop()
                    localAudioTrack.flush()
                }
                localAudioTrack?.release()
            } catch (e: Exception) {
                // 忽略释放异常
            }
            
            // 更新UI状态
            withContext(Dispatchers.Main) {
                isPlaying.value = false
            }
        }
    }
    
    private fun stopAudio() {
        coroutineScope.launch {
            stopAudioImmediately()
        }
    }
    
    override fun onPause() {
        super.onPause()
        stopAudio()
    }
    
    override fun onDestroy() {
        coroutineScope.launch {
            stopAudioImmediately()
        }
        super.onDestroy()
    }
}

@Composable
fun AudioTestScreen(
    modifier: Modifier = Modifier,
    hasPermission: Boolean,
    isPlaying: Boolean,
    onRequestPermission: () -> Unit,
    onPlayMusic: (Int) -> Unit,
    onPlayVoiceCall: (Int) -> Unit,
    onPlaySystem: (Int) -> Unit,
    onPlayRing: (Int) -> Unit
) {
    Column(
        modifier = modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        if (!hasPermission) {
            Text(text = "需要存储权限才能播放音频")
            Spacer(modifier = Modifier.height(8.dp))
            Button(onClick = { onRequestPermission() }) {
                Text(text = "点击请求权限")
            }
            Spacer(modifier = Modifier.height(24.dp))
        }
        
        Button(
            onClick = { onPlayMusic(AudioManager.STREAM_MUSIC) },
            enabled = hasPermission
        ) {
            Text(text = "播放音乐流(STREAM_MUSIC)")
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        Button(
            onClick = { onPlayVoiceCall(AudioManager.STREAM_VOICE_CALL) },
            enabled = hasPermission
        ) {
            Text(text = "播放通话流(STREAM_VOICE_CALL)")
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        Button(
            onClick = { onPlaySystem(AudioManager.STREAM_SYSTEM) },
            enabled = hasPermission
        ) {
            Text(text = "播放系统流(STREAM_SYSTEM)")
        }
        
        Spacer(modifier = Modifier.height(16.dp))
        
        Button(
            onClick = { onPlayRing(AudioManager.STREAM_RING) },
            enabled = hasPermission
        ) {
            Text(text = "播放铃声流(STREAM_RING)")
        }
        
        if (isPlaying) {
            Spacer(modifier = Modifier.height(16.dp))
            Text(text = "正在播放中...")
        }
    }
} 